package umg.util;



import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import umg.gui.GUI;
import umg.vo.MatchSnapShotVO;
import umg.vo.PlayerVO;

public class XMLUtil {
	
	//parse the xml file and get the dom object
	public static ArrayList<MatchSnapShotVO> readXmlFile(String filename){
		ArrayList<MatchSnapShotVO> matches=null;
		
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		try {
			
			//Using factory get an instance of document builder
			DocumentBuilder db = dbf.newDocumentBuilder();
			//parse using builder to get DOM representation of the XML file
			Document dom = db.parse(filename);
			matches=parseMatchData(dom);

		}catch(ParserConfigurationException pce) {
			pce.printStackTrace();
		}catch(SAXException se) {
			se.printStackTrace();
		}catch(IOException ioe) {
			//File not found
			if (ioe instanceof FileNotFoundException)
			{}
			else
			ioe.printStackTrace();
		}
		return matches;
	}

	private static ArrayList<MatchSnapShotVO> parseMatchData(Document dom)
	{
		ArrayList<MatchSnapShotVO> matches= new ArrayList<MatchSnapShotVO>();
		//get the root elememt
		Element docEle = dom.getDocumentElement();
		
		NodeList nl = docEle.getElementsByTagName("Match");
		if(nl != null && nl.getLength() > 0) {
			for(int i = 0 ; i < nl.getLength();i++) {
				
				Element el = (Element)nl.item(i);
				
				//get the Employee object
				MatchSnapShotVO match = getMatchSnapShotVO(el);
				
				//add it to list
				matches.add(match);
			}
		}
		GUI.logToStatus("Parsed "+matches.size()+" matches from xml.");
		if(PropertyManager.isDebug())printToConsole(matches);
		return matches;
	}


	@SuppressWarnings("deprecation")
	private static MatchSnapShotVO getMatchSnapShotVO(Element match) 
	{
		MatchSnapShotVO matchVO= new MatchSnapShotVO();
		matchVO.setTimestamp(new Date(match.getAttribute("timestamp")));
		
		//get all the players
		NodeList nl = match.getElementsByTagName("Player");
		
		if(nl != null && nl.getLength() > 0) 
		{
			PlayerVO players[]= new PlayerVO[nl.getLength()];
			for(int i=0;i<nl.getLength();i++)
			{
				Element el = (Element)nl.item(i);
				//this is a player node. it will have 5 attributes.
				PlayerVO player= new PlayerVO();
				player.setPlayerName(el.getAttribute("alias"));
				player.setIP(el.getAttribute("ip"));
				player.setScore(el.getAttribute("score"));
				player.setPing(el.getAttribute("ping"));
				player.setTeam(el.getAttribute("team"));
				players[i]=player;
			}
			matchVO.setPlayers(players);		
		}
		
		return matchVO;
	}
	
	/**
	 * Iterate through the list and print the 
	 * content to console
	 */
	public static void printToConsole(ArrayList<MatchSnapShotVO> matches){
		
		System.out.println("No. of Matches read: " + matches.size());
		
		Iterator<MatchSnapShotVO> it = matches.iterator();
		while(it.hasNext()) {
			MatchSnapShotVO match= it.next();
			System.out.println("Match @ "+match.getTimestamp());
			PlayerVO[] players=match.getPlayers();
			System.out.println("Player count: "+players.length);
			for(int i=0;i<players.length;i++)
				System.out.println("\t ["+players[i].toString()+"]");
			System.out.println("--------------------");
		}
	}
	
	public static void saveXmlFile(String filename, ArrayList<MatchSnapShotVO> matches)
	{
		Document dom = null;

		//get an instance of factory
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		try {
		//get an instance of builder
		DocumentBuilder db = dbf.newDocumentBuilder();

		//create an instance of DOM
		dom = db.newDocument();
		
		//create the root element <matches>
		Element rootEle = dom.createElement("Matches");
		dom.appendChild(rootEle);
		
		for (MatchSnapShotVO match: matches)
		{
			//For each MatchSnapShotVO object  create <Match> element and attach it to root
			Element matchElement = createMatchElement(match,dom);
			rootEle.appendChild(matchElement);
		}
		
		//now print to the file.
		printToFile(dom,filename);
		

		}catch(ParserConfigurationException pce) {
			//dump it
			System.out.println("Error while trying to instantiate DocumentBuilder " + pce);
			pce.printStackTrace();
		}

	}

	private static Element createMatchElement(MatchSnapShotVO match, Document dom)
	{
		Element matchEle = dom.createElement("Match");
		matchEle.setAttribute("timestamp", match.getTimestamp().toString());

		for (PlayerVO player: match.getPlayers())
		{
			//add player child elements to the match
			Element playerEle = dom.createElement("Player");
			playerEle.setAttribute("alias", player.getPlayerName());
			playerEle.setAttribute("ip", player.getIP());
			playerEle.setAttribute("score", player.getScore());
			playerEle.setAttribute("ping", player.getPing());
			playerEle.setAttribute("team", player.getTeam());
			matchEle.appendChild(playerEle);			
		}
		return matchEle;
	}
	
	private static void printToFile(Document dom, String filename){
		Transformer transformer;
		try
		{
			transformer = TransformerFactory.newInstance().newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");

			//initialize StreamResult with File object to save to file

			StreamResult result = new StreamResult(new File(filename));
			DOMSource source = new DOMSource(dom);
			transformer.transform(source, result);	

		}
		catch (TransformerConfigurationException e1)
		{
			e1.printStackTrace();
		}
		catch (TransformerFactoryConfigurationError e1)
		{
			e1.printStackTrace();
		}
		catch (TransformerException e)
		{
			e.printStackTrace();
		}



	}


}
